package chpt09.testsync;

import java.util.LinkedList;
import java.util.List;

public class ProducerConsumerV2{
	public static void main(String[] args) throws InterruptedException {
		RepositoryV2 repo = new RepositoryV2();
		Thread p1 = new Thread(new ProducerV2(repo, 30000));
		Thread c1 = new Thread(new ConsumerV2(repo, 10000));
		Thread c2 = new Thread(new ConsumerV2(repo, 10000));
		Thread c3 = new Thread(new ConsumerV2(repo, 10000));
		p1.start();
		c1.start();
		c2.start();
		c3.start();
		p1.join();
		c1.join();
		c2.join();
		c3.join();
		System.out.format("仓库还剩%d个货物%n", repo.size());
	}
}

class RepositoryV2 { // 存放字符串的仓库
	private int capacity = 10; // 仓库容量默认为10
	private List<String> repo = new LinkedList<>();

	public synchronized void add(String t) throws InterruptedException {
		while (size() == capacity) {
			wait();
		}
		repo.add(t);
		notifyAll();// 通知其他线程醒来
	}

	public synchronized String remove() throws InterruptedException {
		while (size() == 0) {
			wait();
		}
		String x = repo.remove(0);
		notifyAll();
		return x;
	}

	public int getCapacity() { // 返回仓库容量
		return capacity;
	}

	public synchronized int size() {
		return repo.size();
	}

	

}

class ProducerV2 implements Runnable {

	private RepositoryV2 repo;
	private int num; // 让Producer放入num次

	public ProducerV2(RepositoryV2 repo, int num) {
		this.repo = repo;
		this.num = num;
	}

	@Override
	public void run() {
		String name = Thread.currentThread().getName();
		for (int i = 0; i < num; i++) {
			try {
				repo.add(new String("sth"));
			} catch (InterruptedException e) {
				System.err.printf("%s放入货物失败", name);
			}
		}
		System.out.format("%s放入(%d)个货物完毕!%n", name, num);
	}
}

class ConsumerV2 implements Runnable {
	private RepositoryV2 repo;
	private int num;// 让Consumer取num次

	public ConsumerV2(RepositoryV2 repo, int num) {
		this.repo = repo;
		this.num = num;
	}

	@Override
	public void run() {
		int n = 0;
		String name = Thread.currentThread().getName();
		for (int i = 0; i < num; i++) {
			String x = null;
			try {
				x = repo.remove();
			} catch (InterruptedException e) {
				System.err.printf("%s取出货物失败", name);
			}
			if (x != null)
				n++;
		}
		System.out.format("%s取出(%d/%d)个货物完毕!%n", name, n, num);
	}
}